package com.stox.client.ui.javafx.workbench.stage;

import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.stage.Screen;

public class StageResizeRelocateMouseEventHandler  implements
EventHandler<MouseEvent> {

	public void applyStageResizeRelocateMouseEventHandler(StoxStage stage) {
		this.stage = stage;
		
		stage.addEventHandler(MouseEvent.MOUSE_PRESSED, this);
		stage.addEventHandler(MouseEvent.MOUSE_MOVED, this);
		stage.addEventHandler(MouseEvent.MOUSE_DRAGGED, this);
		stage.addEventHandler(MouseEvent.MOUSE_EXITED, this);

		stage.getTitleBar().addEventHandler(MouseEvent.MOUSE_PRESSED,this);
		stage.getTitleBar().addEventHandler(MouseEvent.MOUSE_MOVED, this);
		stage.getTitleBar().addEventHandler(MouseEvent.MOUSE_DRAGGED,this);
		stage.getTitleBar().addEventHandler(MouseEvent.MOUSE_CLICKED,this);
	}

	private StoxStage stage;
	private double offsetX;
	private double offsetY;
	private double border = 4;
	private boolean active = false;

	@Override
	public void handle(MouseEvent event) {
		double x = event.getScreenX();
		double y = event.getScreenY();
		
		if (MouseEvent.MOUSE_MOVED.equals(event.getEventType())) {
			setCursor(x, y);
		} else if (MouseEvent.MOUSE_PRESSED.equals(event.getEventType())) {
			offsetX = event.getSceneX();
			offsetY = event.getSceneY();
		} else if (MouseEvent.MOUSE_DRAGGED.equals(event.getEventType())) {
			if(Cursor.DEFAULT.equals(stage.getScene().getCursor()) && 
					y < stage.getY() + stage.getTitleBar().getLayoutY() + stage.getTitleBar().getHeight()){
				relocate(x, y);
			}else{
				resize(x, y);
			}
		}else if(MouseEvent.MOUSE_CLICKED.equals(event.getEventType()) && event.getClickCount() == 2){
			toggleMaximized();
		}
	}
	
	public void toggleMaximized(){
		double x = stage.getX() < 0 ? 0 : stage.getX();
		double y = stage.getY() < 0 ? 0 : stage.getY();
		Screen screen = (Screen)Screen.getScreensForRectangle(x, y, 1d, 1d).get(0);
		
		if (stage.isMaximized()) {
			stage.setMaximized(false);
			if (stage.getBackupWindowBounds() != null) {
				stage.setX(stage.getBackupWindowBounds().getMinX());
				stage.setY(stage.getBackupWindowBounds().getMinY());
				stage.setWidth(stage.getBackupWindowBounds().getWidth());
				stage.setHeight(stage.getBackupWindowBounds().getHeight());
			}
		} else {
			stage.setMaximized(true);
			stage.setBackupWindowBounds(new Rectangle2D(stage.getX(),stage.getY(),stage.getWidth(),stage.getHeight()));
			stage.setX(screen.getVisualBounds().getMinX());
			stage.setY(screen.getVisualBounds().getMinY());
			stage.setWidth(screen.getVisualBounds().getWidth());
			stage.setHeight(screen.getVisualBounds().getHeight());
		}
	}
	
	private void relocate(double x, double y){
		stage.setX(x - offsetX);
		stage.setY(y - offsetY); 
	}

	private void setCursor(double x, double y){
		Scene scene = stage.getScene();
		double stageX = stage.getX();
		double stageY = stage.getY();
		double stageHeight = stage.getHeight();
		double stageWidth = stage.getWidth();
		
		 if (x < stageX + border && y < stageY + border) {
				scene.setCursor(Cursor.NW_RESIZE);
				active = true;
			} else if(x > stageX + stageWidth - border && y < stageY + border){
				scene.setCursor(Cursor.NE_RESIZE);
				active = true;
			}else if(x > stageX + stageWidth - border && y > stageY + stageHeight - border){
				scene.setCursor(Cursor.SE_RESIZE);
				active = true;
			}else if(x < stageX + border && y > stageY + stageHeight - border){
				scene.setCursor(Cursor.SW_RESIZE);
				active = true;
			}else if (x < stageX + border) {
				scene.setCursor(Cursor.W_RESIZE);
				active = true;
			}else if (y < stageY + border) {
				scene.setCursor(Cursor.N_RESIZE);
				active = true;
			}else if(x > stageX + stageWidth - border){
				scene.setCursor(Cursor.E_RESIZE);
				active = true;
			}else if(y > stageY + stageHeight - border){
				scene.setCursor(Cursor.S_RESIZE);
				active = true;
			}else {
				if(active){
					scene.setCursor(Cursor.DEFAULT);
					active = false;
				}
			}
	}
	
	private void resize(double x, double y){
		double minWidth = stage.getWidth() > stage.getMinWidth() ? stage.getMinWidth() : border*2;
		double minHeight = stage.getHeight() > stage.getMinHeight() ? stage.getMinHeight() : border*2;
		Cursor cursor = stage.getScene().getCursor();
		if(Cursor.W_RESIZE.equals(cursor)){
			resizeWest(minWidth, x);
		}else if(Cursor.NW_RESIZE.equals(cursor)){
			resizeWest(minWidth, x);
			resizeNorth(minHeight, y);
		}else if(Cursor.N_RESIZE.equals(cursor)){
			resizeNorth(minHeight, y);
		}else if(Cursor.NE_RESIZE.equals(cursor)){
			resizeNorth(minHeight, y);
			resizeEast(minWidth, x);
		}else 	if(Cursor.E_RESIZE.equals(cursor)){
			resizeEast(minWidth, x);
		}else if(Cursor.SE_RESIZE.equals(cursor)){
			resizeEast(minWidth, x);
			resizeSouth(minHeight, y);
		}else if(Cursor.S_RESIZE.equals(cursor)){
			resizeSouth(minHeight, y);
		}else if(Cursor.SW_RESIZE.equals(cursor)){
			resizeSouth(minHeight, y);
			resizeWest(minWidth, x);
		}
	}
	
	private void resizeWest(double minWidth, double x){
		double w = stage.getX() + stage.getWidth() - x;
		if(w >= minWidth){
			stage.setWidth(w);
			stage.setX(x);
		}
	}
	
	private void resizeNorth(double minHeight, double y){
		double h = stage.getY() + stage.getHeight() - y;
		if(h >= minHeight ){
			stage.setHeight(h);
			stage.setY(y);
		}
	}
	
	private void resizeEast(double minWidth, double x){
		double w = x - stage.getX();
		if(w >= minWidth){
			stage.setWidth(w);
		}
	}
	
	private void resizeSouth(double minHeight, double y){
		double h = y - stage.getY();
		if(h >= minHeight ){
			stage.setHeight(h);
		}
	}
	
	

}
